{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Downloading Overlays\n",
    "\n",
    "This notebook demonstrates how to download an FPGA overlay and examine programmable logic state.  \n",
    "\n",
    "## 1. Instantiating an overlay\n",
    "With the following overlay bundle present in the `overlays` folder, users can instantiate the overlay easily.\n",
    "\n",
    "*  A bitstream file (\\*.bit).\n",
    "*  A tcl file (\\*.tcl), or an hwh file (\\*.hwh).\n",
    "*  A python class (\\*.py).\n",
    "\n",
    "For example, an overlay called `base` can be loaded by:\n",
    "```python\n",
    "from pynq.overlays.base import BaseOverlay\n",
    "overlay = BaseOverlay(\"base.bit\")\n",
    "```\n",
    "Users can also use the absolute file path of the bitstream to instantiate the overlay.\n",
    "\n",
    "In the following cell, we get the current bitstream loaded on PL, and try to download it multiple times."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq import PL\n",
    "from pynq import Overlay\n",
    "\n",
    "ol = Overlay(PL.bitfile_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can check the download timestamp for this overlay."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2018/6/29 21:41:41 +300176'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ol.download()\n",
    "ol.timestamp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Examining the PL state\n",
    "\n",
    "While there can be multiple overlay instances in Python, there is only one bitstream that is currently loaded onto the programmable logic (PL). \n",
    "\n",
    "This bitstream state is held in the singleton class, PL, and is available for user queries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/usr/local/lib/python3.6/dist-packages/pynq/overlays/base/base.bit'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "PL.bitfile_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2018/6/29 21:41:41 +300176'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "PL.timestamp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Users can verify whether an overlay instance is currently loaded using the Overlay is_loaded() method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ol.is_loaded()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Overlay downloading overhead\n",
    "\n",
    "Finally, using Python, we can see the bitstream download time over 50 downloads.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0xad382ed0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import time\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "length = 50\n",
    "time_log = []\n",
    "for i in range(length):\n",
    "    start = time.time()\n",
    "    ol.download()\n",
    "    end = time.time()\n",
    "    time_log.append((end-start)*1000)\n",
    "\n",
    "%matplotlib inline\n",
    "plt.plot(range(length), time_log, 'ro')\n",
    "plt.title('Bitstream loading time (ms)')\n",
    "plt.axis([0, length, 0, 1000])\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
